Skip to content

fix(vue): Prevent TDZ error in watch callbacks#7743

Merged
wobsoriano merged 5 commits into
mainfrom
rob/prevent-tdz-error
Feb 3, 2026
Merged

fix(vue): Prevent TDZ error in watch callbacks#7743
wobsoriano merged 5 commits into
mainfrom
rob/prevent-tdz-error

Conversation

@wobsoriano
Copy link
Copy Markdown
Member

@wobsoriano wobsoriano commented Feb 3, 2026

Description

This PR fixes an error occurring in Vue composables where watchers attempted to call unwatch() within their own initialization.

Fixes https://discord.com/channels/856971667393609759/1468208882378739765

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Summary by CodeRabbit

  • Bug Fixes
    • Prevented duplicate watcher invocations during Vue SDK initialization, improving stability.
  • Tests
    • Added comprehensive tests validating one-time callback invocation, immediate invocation cases, state transitions, and watcher cleanup to ensure reliable behavior.

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Feb 3, 2026 5:34pm

Request Review

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Feb 3, 2026

🦋 Changeset detected

Latest commit: c664395

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@clerk/vue Patch
@clerk/nuxt Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 3, 2026

📝 Walkthrough

Walkthrough

Adds a changeset for a patch release to the @clerk/vue package and updates several composables to fix watcher initialization/unwatch behavior. Files modified: useAuth.ts, useOrganization.ts, useSignIn.ts, useSignUp.ts, and useClerkLoaded.ts — converting manual unwatch patterns to Vue's one-shot behavior or capturing/unwatching safely when immediate invocation is required. Adds tests for useClerkLoaded covering load state transitions and watcher cleanup. No public API or exported declarations were changed.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(vue): Prevent TDZ error in watch callbacks' accurately describes the main objective of the PR, which is to fix temporal dead zone errors in Vue composables where watchers call unwatch() during initialization.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Feb 3, 2026

Open in StackBlitz

@clerk/agent-toolkit

npm i https://pkg.pr.new/@clerk/agent-toolkit@7743

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@7743

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@7743

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@7743

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@7743

@clerk/dev-cli

npm i https://pkg.pr.new/@clerk/dev-cli@7743

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@7743

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@7743

@clerk/express

npm i https://pkg.pr.new/@clerk/express@7743

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@7743

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@7743

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@7743

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@7743

@clerk/react

npm i https://pkg.pr.new/@clerk/react@7743

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@7743

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@7743

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@7743

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@7743

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@7743

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@7743

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@7743

commit: c664395

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/vue/src/composables/useOrganization.ts (1)

59-71: ⚠️ Potential issue | 🟠 Major

Bump Vue peer dependency or replace { once: true } with manual unwatch in useOrganization, useSignIn, and useSignUp.

The once option for watch() was introduced in Vue 3.4, but packages/vue/package.json specifies "vue": "^3.2.0". Users on Vue 3.2 or 3.3 will not get the intended one-shot behavior. Either bump the peer dependency to "^3.4.0" or switch to the manual unwatch pattern already used elsewhere in the codebase (e.g., useClerkLoaded.ts and useAuth.ts).

Comment on lines +20 to 32
let unwatch: (() => void) | undefined;
// eslint-disable-next-line prefer-const
unwatch = watch(
clerk,
unwrappedClerk => {
if (!unwrappedClerk?.loaded) {
return;
}

callback(unwrappedClerk as LoadedClerk);
unwatch?.();
},
{ immediate: true },
Copy link
Copy Markdown
Member Author

@wobsoriano wobsoriano Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are not using the once option here as we also need to wait for the loaded value of Clerk to be true and the once option will stop the watcher once clerk has a value

@wobsoriano wobsoriano changed the title fix(vue): prevent TDZ error in watch callbacks fix(vue): Prevent TDZ error in watch callbacks Feb 3, 2026
Comment on lines +35 to +43
watch(
clerk,
value => {
if (value) {
value.telemetry?.record(eventMethodCalled('useSignIn'));
}
},
{ once: true },
);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: Why not use the useClerkLoaded helper?

A: Telemetry can be recorded as soon as the clerk instance exists. We don't have to wait for Clerk to be loaded

@wobsoriano
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 3, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Member

@jacekradko jacekradko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Nice work

@wobsoriano wobsoriano merged commit 6d960a8 into main Feb 3, 2026
64 of 65 checks passed
@wobsoriano wobsoriano deleted the rob/prevent-tdz-error branch February 3, 2026 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants